package it.sebsibenal.client.pages;

import it.sebsibenal.client.GreetingService;
import it.sebsibenal.client.GreetingServiceAsync;
import it.sebsibenal.client.pages.EditableHTML.EditCommand;
import it.sebsibenal.client.pages.NuovoBranoDialog.SaveHandler;
import it.sebsibenal.client.pages.YoutubeVideoPanel.RemoveLinkHandler;
import it.sebsibenal.shared.Operazione;
import it.sebsibenal.shared.Song;

import java.util.Iterator;
import java.util.List;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.StackLayoutPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
import com.google.gwt.view.client.SingleSelectionModel;

public class SongEditor extends Composite {

	private static final String DESCRIZIONE_EMPTY = "<i>Descrizione brano</i>";
	private static final String TESTO_EMPTY = "<i>Testo brano</i>";
	
	
	private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
	public static final String PAGE_NAME = "songEditor";
	
	private static SongEditorUiBinder uiBinder = GWT.create(SongEditorUiBinder.class);

	interface SongEditorUiBinder extends UiBinder<Widget, SongEditor> {
	}

	@UiField TabLayoutPanel tabs;
	
	@UiField CellList<Song> listaBrani;
	@UiField StackLayoutPanel elencoBrani;
	
	@UiField EditableHTML autore; 
	@UiField EditableHTML titolo;
	
	@UiField EditableHTML descrizione;
	
	@UiField EditableHTML testo;
	
	PopupPanel modificaPp = new PopupPanel(true);
	HTML modificaHtml;

	@UiField TextBox linkVideo;
	@UiField VerticalPanel videoPanel;
	
	@UiField TextArea commento;
	@UiField VerticalPanel bacheca;
	
	Song selectedSong;
	
	SaveSongCallback saveCallback = new SaveSongCallback(null);
	

	public SongEditor() {
		this("");
	}

	public SongEditor(String firstName) {
		initWidget(uiBinder.createAndBindUi(this));
		modificaHtml = new HTML("Modifica"); 
		modificaPp.add(modificaHtml);
		modificaPp.setAnimationEnabled(true);
		autore.setEditCommand(new EditSongCommand() {
			@Override
			void setField(String html) {
				selectedSong.setAutore(html);
			}
		});
		titolo.setEditCommand(new EditSongCommand() {
			@Override
			void setField(String text) {
				selectedSong.setTitolo(text);
			}
		});
		descrizione.setEditCommand(new EditSongCommand() {
			@Override
			void setField(String text) {
				selectedSong.setDescrizione(text);
			}
		});
		testo.setEditCommand(new EditSongCommand() {
			@Override
			void setField(String text) {
				selectedSong.setTesto(text);
			}
		});
	}

	@UiFactory
	public CellList<Song> createListaBrani() {
		final CellList<Song> res = new CellList<Song>(new AbstractCell<Song>() {
			@Override
			public void render(com.google.gwt.cell.client.Cell.Context context, Song value, SafeHtmlBuilder sb) {
				sb.appendEscaped(value.getTitolo());
			}
		});
		
		final SingleSelectionModel<Song> braniSelectionModel = new SingleSelectionModel<Song>();
		res.setSelectionModel(braniSelectionModel);
		braniSelectionModel.addSelectionChangeHandler(new Handler() {
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				songSelected(braniSelectionModel.getSelectedObject());
			}
		});
		return res;
	}

	public void songSelected(Song song) {
		selectedSong = song;
		bindSong(song);
	}
	
	private void bindSong(final Song song) {
		autore.setHTML(song.getAutore());
		titolo.setHTML(song.getTitolo());
		descrizione.setHTML(song.getDescrizione()!=null? song.getDescrizione(): DESCRIZIONE_EMPTY);
		testo.setHTML(song.getTesto()!=null? song.getTesto():TESTO_EMPTY);
		videoPanel.clear();
		bacheca.clear();
		commento.setText("");
		for (Iterator<String> iterator = song.getYoutubeLinks().iterator(); iterator.hasNext();) {
			String link = iterator.next();
			YoutubeVideoPanel vp = new YoutubeVideoPanel(link);
			vp.setRemoveLinkHandler(new RemoveLinkHandler() {
				@Override
				public void onLinkRemove(String link) {
					greetingService.removeYoutubeLink(link, song, saveCallback);
				}
			});
			videoPanel.add(vp);
		}
		if (song.getYoutubeLinks().size()>0) {
			tabs.setTabHTML(2, "Video (" + song.getYoutubeLinks().size()+")");
		} else {
			tabs.setTabHTML(2, "Video");
		}
		if (song.getCommenti().size()>0) {
			tabs.setTabHTML(3, "Commenti (" + song.getCommenti().size()+")");
		} else {
			tabs.setTabHTML(3, "Commenti");
		}
		linkVideo.setText("");
		autore.setEditable(false);
		titolo.setEditable(false);
		descrizione.setEditable(false);
		testo.setEditable(false);
		for (int i = song.getCommenti().size()-1;  i >= 0; i--) {
			String commento = song.getCommenti().get(i);
			HTML htmlCommento = new HTML(commento);
			htmlCommento.addStyleName("commento");
			bacheca.add(htmlCommento);
			bacheca.setCellWidth(htmlCommento, "100%");
		}
	}
	
	public void go() {
		go(null);
	}

	public void go(final Song selectedSong) {
		greetingService.getSongs(new AsyncCallback<List<Song>>() {
			@Override
			public void onSuccess(List<Song> result) {
				if (result.size()>0) {
					listaBrani.setRowData(result);
					elencoBrani.setHeaderHTML(0, "Brani (" + result.size() + ")");
					listaBrani.getSelectionModel().setSelected(selectedSong!=null?selectedSong:result.get(0), true);
					songSelected(selectedSong!=null?selectedSong:result.get(0));
				}
			}
			
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Errore nella lettura dei brani");
			}
		});
	}

	@UiHandler("aggiungiVideo")
	public void aggiungiVideo(ClickEvent event) {
		String link = linkVideo.getText();
		if (link!=null && link.trim().length()>0) {
			if (validaLink(link)) {
				if (!selectedSong.getYoutubeLinks().contains(link)) {
					greetingService.addYoutubeLink(link, selectedSong, saveCallback);
				} else {
					Window.alert("Il video e' gia' presente nella lista");
				}
			} else {
				Window.alert("Codice youtube non valido. Inserire solo il codice, non tutto l'indirizzo");
			}
		}
	}
	
	
	private boolean validaLink(String link) {
		return !(link.indexOf("http")>-1);
	}

	@UiHandler("aggiungiBrano")
	public void aggiungiBrano(ClickEvent event) {
		final NuovoBranoDialog dialog = new NuovoBranoDialog();
		dialog.addSaveHandler(new SaveHandler() {
			@Override
			public void onClick(ClickEvent event) {
				String autore = dialog.getAutore();
				String titolo = dialog.getTitolo();
				if (autore.trim().length()==0) {
					Window.alert("Inserire un autore");
					return;
				}
				if (titolo.trim().length()==0) {
					Window.alert("Inserire un titolo");
					return;
				}
				final Song song = new Song();
				song.setAutore(autore);
				song.setTitolo(titolo);
				greetingService.saveSong(song, Operazione.NUOVO_BRANO, new SaveSongCallback(new AsyncCallback<Song>() {
					@Override
					public void onSuccess(Song result) {
						confirmSave();
					}
					@Override
					public void onFailure(Throwable caught) {
						errorOnSave(caught);
					}
				}));
			}
		});
		dialog.setModal(true);
		dialog.setAutoHideEnabled(false);
		dialog.setAnimationEnabled(true);
		dialog.setGlassEnabled(true);
		dialog.show();
	}
	
	@UiHandler("aggiungiCommento")
	public void aggiungiCommento(ClickEvent event) {
		String text = commento.getText();
		greetingService.addComment("<p>"+text+"<p>", selectedSong, saveCallback);
	}
	
	@UiField TextBox folderName;
	@UiField HTMLPanel cartelle;
	
	@UiHandler("aggiungiCartella")
	public void aggiungiCartella(ClickEvent event) {
		//greetingService.aggiungiCartella(folderName.getText(), saveCallback);
		greetingService.elencoCartelle(new AsyncCallback<String>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("ERRORE!");
			}

			@Override
			public void onSuccess(String result) {
				cartelle.add(new HTML(result));
			}
		});
	}
	
	
	class SaveSongCallback implements AsyncCallback<Song> {
		private AsyncCallback<Song> callback;
		
		public SaveSongCallback(AsyncCallback<Song> callback) {
			super();
			this.callback = callback;
		}

		@Override
		public void onSuccess(Song result) {
			if (callback!=null) callback.onSuccess(result);
			go(result);
		}
		
		@Override
		public void onFailure(Throwable caught) {
			Window.alert("Errore nel salvataggio del brano");
			if (callback!=null) callback.onFailure(caught);
		}
	}

	
	abstract class EditSongCommand implements EditCommand<Song> {
		@Override
		public void onSave(final String text, Operazione operazione, final AsyncCallback<Song> callback) {
			setField(text); 
			greetingService.saveSong(selectedSong, operazione, new SaveSongCallback(callback));
		}

		abstract void setField(String text);

		@Override
		public void onCancel() {}
		
	}

}
